package com.cdy.client;

import com.cdy.client.netty.NettyClient;
import com.cdy.common.command.DownloadCommand;
import com.cdy.common.command.RequestDownloadCommand;
import com.cdy.common.command.UploadCommand;
import com.cdy.common.domain.FileEntity;
import com.cdy.common.domain.FileSectionEntity;
import com.cdy.common.property.CommonProperty;
import com.cdy.common.response.RequestDownloadResponse;
import com.cdy.common.response.Response;
import com.cdy.common.uitl.FileUtil;
import org.apache.commons.codec.digest.DigestUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.BitSet;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;

/**
 * 文件客户端
 * Created by 陈东一
 * 2019/10/19 0019 17:04
 */
public class FileDownloadClient {

    public static BlockingQueue<UploadCommand> queue = new ArrayBlockingQueue<>(1000);
    public static volatile Boolean isFinish = false;
    public static File file;
    // sectionId ->
    public static ConcurrentHashMap<Long, FileChannel> fileMap = new ConcurrentHashMap<>();
    // sectionId ->
    public static ConcurrentHashMap<Long, FileSectionEntity> sectionMap = new ConcurrentHashMap<>();
    public static File backupFile;

    public static void main(String[] args) throws Exception {
//        backupFile = new File("d:"+File.separator+"sectionMap.json");
//        if (!backupFile.exists()) {
//            backupFile.createNewFile();
//        }

        System.setProperty("io.netty.buffer.checkBounds", "false");
        file = new File("d:"+File.separator+"ArrayDemo.class");
        FileInputStream data = new FileInputStream(file);
        String md5 = DigestUtils.md5Hex(data);
        data.close();
        CommonProperty commonProperty = new CommonProperty();
        NettyClient nettyClient = new NettyClient(commonProperty);
        nettyClient.connect("127.0.0.1", 12345);

        RequestDownloadCommand requestCommand = new RequestDownloadCommand();
        requestCommand.setFileMD5(md5);
        requestCommand.setClientId(commonProperty.getClientId());
        @SuppressWarnings("unchecked")
        Future<Response> send = (Future<Response>) nettyClient.send(requestCommand).orElseThrow(RuntimeException::new);
        Response response = send.get();
        RequestDownloadResponse requestResponse = (RequestDownloadResponse) response;
        if (requestResponse.getComplete()) {
            return;
        } else {
            FileEntity fileEntity = requestResponse.getFileEntity();
            List<FileSectionEntity> list = requestResponse.getList();
            for (FileSectionEntity sectionEntity : list) {
                fileMap.put(sectionEntity.getId(), FileUtil.openChannel(FileUtil.openFile("d:"+File.separator+"downloadTemp"+File.separator + fileEntity.getName() + "-" + sectionEntity.getId())));
                DownloadCommand downloadCommand = initDownloadCommand(commonProperty, sectionEntity);
                nettyClient.send(downloadCommand);
                // 检测 从分配分段是否下载完成 todo
            }

            while (true) { // 是否整个文件都上传完成
                boolean fileComplete = list.stream().anyMatch(e -> !e.getComplete());
                // todo 持久化文件
                System.out.println(sectionMap.toString());
                if (fileComplete) {
                    fileEntity.setComplete(true);
                    break;
                } else {
                    Thread.sleep(1000L);
                }
            }
        }
        nettyClient.close();
        fileMap.values().forEach(e-> {
            try {
                e.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        });
        System.exit(0);
    }

    public static DownloadCommand initDownloadCommand(CommonProperty commonProperty, FileSectionEntity sectionEntity) {
        DownloadCommand downloadCommand = new DownloadCommand();
        BitSet bitSet = sectionEntity.getBitSet();
        //设置客户端最开始的开始位置
        int begin = bitSet.nextClearBit(0);
        downloadCommand.setBegin(sectionEntity.getBegin() + begin * CommonProperty.SmallSectionLength);
        downloadCommand.setBitBegin(begin);
        int end = bitSet.nextSetBit(begin);
        end = (end == -1) ? sectionEntity.getSectionSize() : end;
        downloadCommand.setBitSize(end - begin);
        downloadCommand.setBitTotal(sectionEntity.getSectionSize());
        downloadCommand.setSectionLength(sectionEntity.getLength());
        downloadCommand.setSectionId(sectionEntity.getId());
        downloadCommand.setSectionBegin(sectionEntity.getBegin());
        downloadCommand.setClientId(commonProperty.getClientId());
        return downloadCommand;
    }
}
